// debug_windows.cpp
// Debug Inspector windows: call stack, local variables, watches.
#include "sframe.h"
#include <sstream>
using namespace std;

void update_debug_windows(ListWindow* excluded);  // in sframe.cpp

bool prompt_for_str(char* caption, char* text, string& s)
{
    char buff[256];
    strcpy(buff,s.c_str());

    TModalLayout (gMainFrame,caption)
     << Width(150) << Field(text,buff,0);

    if (TModalLayout::success()) {
        s = buff;
        return true;
    } else return false;
}

string itos(int i)
{
  return i2a(i);
}

/////// Call Stack Window /////////
// Parses the output of the UCW #fs command (which shows the current stack frame)
// and displays this as a list.  Double-click causes the IDE to go to that
// position in the function (via the Position::action() method) and then
// we call #ff to set the UCW current stack frame.

CallStackWindow::CallStackWindow()
: ListWindow("Function Call Stack")
 {
 }

// override to perform extra action
void CallStackWindow::double_clicked(int idx, ItemObject* obj)
{
      gMainFrame->ucw()->exec("#ff " + itos(idx));
      update_debug_windows(this);
}

// required override to fill list
void CallStackWindow::fill_list()
{
   string res;
   gMainFrame->ucw()->exec_msg("#fs",res);      
   istringstream ins(res);
   int idx,lineno;
   string file, fun;
   Position* obj;
   while (! ins.eof()) {
     ins >> idx >> file >> lineno;
     getline(ins,fun);
  // note: the given position is off -- *DEBUG*
     obj = new Position(file,lineno-2);
     add(fun,obj);
   }
}

////// Local Variables Window ////////
// simply displays the result of the UCW #lv command in a list

LocalVarsWindow::LocalVarsWindow()
: ListWindow("Local Variables")
{
}

void LocalVarsWindow::fill_list()
{
// we use the UCW #lv command; note if there's a parm we get _all_ locals.
   string res;
   gMainFrame->ucw()->exec_msg("#lv all",res);
   split_text(res,'\n');
}

//////// Watch Variables Window //////////////
// the strategy here is to make the item object relatively intelligent,
// and the list window dumb.  The WatchVar object carries an expression;
// its action() method (which is activated by double-click) edits this
// expression; the WatchVarsWindow::double_click() then updates the text
// of the list using the WatchVar's as_str() method.

class WatchVar: public ItemObject {
    string m_var;
public:
  WatchVar(string v)
    : m_var(v) {}

   void as_str(string& s)
   {
     string res;
     s = m_var + " = ";     
     if (gMainFrame->ucw()->eval(m_var,res)) s += res;
     else s += "???";
   }

   bool action()
   {
      if (m_var == "") 
          SFrame::current_view()->current_word(m_var);
      return prompt_for_str("Edit Watch","variable",m_var);
   }
};

WatchVarsWindow::WatchVarsWindow()
        : ListWindow("Watch",false)
{
     set_editable();
}

void WatchVarsWindow::double_clicked(int idx, ItemObject* obj)
{
    update_item(idx);
}

ItemObject* WatchVarsWindow::on_insert(int idx)
{
   int val = 0;
   WatchVar* obj = new WatchVar("");
   if (obj->action())
       return obj;
   else 
      return NULL;
}



